package com.hdl.handler;

import com.hdl.RpcRequest;
import com.hdl.utils.BeanFactory;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class UserServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        System.out.println("read msg is:" + msg);
        if (msg instanceof RpcRequest){
            RpcRequest obj = (RpcRequest) msg;
            try {
                // 如果业务逻辑执行时间超过5s，客户端主动关闭比客户端的通道连接
                Object result = invoke(obj);
                System.out.println("服务端收到执行结果：" + result);
                ctx.writeAndFlush(result);
            } catch (InvocationTargetException | IllegalAccessException e) {
                e.printStackTrace();
                System.out.println("远程调用异常");
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("服务器处理异常" + cause.getMessage());
    }


    /**
     * 使用反射技术调用方法
     */
    public Object invoke(RpcRequest request) throws InvocationTargetException, IllegalAccessException {
        String className = request.getClassName();
        Object bean = null;
        try {
            bean = BeanFactory.getBean(request.getClazz());
        } catch (Exception e) {
            try {
                bean = BeanFactory.getBean(request.getClassName());
            } catch (Exception ex) {
                e.printStackTrace();
                System.out.println("获取" + className + "的Bean失败！");
            }
        }
        // 获取所有方法
        Method[] declaredMethods = bean.getClass().getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            // 1、判断方法名
            if (!declaredMethod.getName().equals(request.getMethodName())){
                continue;
            }
            // 2、判断个数和参数类型个数
            boolean paramTypesCountFlag = request.getParameterTypes().length == declaredMethod.getParameterTypes().length;
            boolean paramCountFlag = request.getParameters().length == declaredMethod.getParameterCount();
            if (!(paramCountFlag && paramTypesCountFlag)){
                continue;
            }
            // 3、判断参数类型的位置是否正确
            boolean paramTypeAllFlag = true;
            for (int i = 0; i < declaredMethod.getParameterTypes().length; i++) {
                String name = declaredMethod.getParameterTypes()[i].getName();
                String name1 = request.getParameterTypes()[i].getName();
                if (!name.equals(name1)){
                    paramTypeAllFlag = false;
                }
            }
            if (!paramTypeAllFlag){
                continue;
            }
            // 4、调用方法
            return declaredMethod.invoke(bean, request.getParameters());
        }

        return null;
    }
}